<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/9/5 0005
 * Time: 19:24
 */
use app\common\Syn_redis;
class WebSocket
{
    const HOST="0.0.0.0";
    const PORT=9505;
    private $ws;
    private $config=[];
    public function __construct($config=[]){
        $this->ws=new swoole_websocket_server(self::HOST,self::PORT);
        $this->config=array_merge($this->config,$config);
        $this->ws->set($this->config);

        $this->listen("0.0.0.0",9506);
        $this->ws->on("open",[$this,'onOpen']);
        $this->ws->on("WorkerStart",[$this,"onWorkerStart"]);
        $this->ws->on("request",[$this,'onRequest']);
        $this->ws->on("message",[$this,'onMessage']);
        $this->ws->on("close",[$this,'onClose']);

        $this->ws->on("task",[$this,'onTask']);
        $this->ws->on("finish",[$this,'onFinish']);
        $this->ws->start();
    }

    /**
     * @Notes:监听ws端口
     * @Interface listen
     * @param $port
     * @author: Chenrui
     * @Time: 2018/9/8 0008   20:26
     */
    public function listen($ip,$port){
        $srv=$this->ws->listen($ip,$port,SWOOLE_SOCK_TCP);
        $srv->on("message",[$this,"onMessage"]);
    }

    public function onWorkerStart($server,$worker_id){
        // 定义应用目录
        define('APP_PATH', __DIR__ . '/../application/');
        // 1. 加载基础文件
        require __DIR__ . '/../thinkphp/start.php';

        $members=Syn_redis::getInstance()->SMEMBERS(\think\Config::get("syn_redis.user"));
        if($members){
            foreach ($members as $key){
                Syn_redis::getInstance()->SREM(\think\Config::get("syn_redis.user"),$key);
            }
        }

    }

    /*
    监听http消息事件
    */
    public function onRequest($req,$res){
        $_SERVER=[];$_GET=[];$_POST=[];$_FILES=[];

        $_SERVER["ws_server"]=$this->ws;
        if(isset($req->server)){
            foreach($req->server as $key =>$val){
                $_SERVER[strtoupper($key)]=$val;
            }
        }

        if(isset($req->header)){
            foreach($req->header as $key =>$val){
                $_SERVER[strtoupper($key)]=$val;
            }
        }

        if(isset($req->files)){
            foreach($req->files as $key =>$val){
                $_FILES[$key]=$val;
            }
        }

        if(isset($req->get)){
            foreach($req->get as $key =>$val){
                $_GET[$key]=$val;
            }
        }

        if(isset($req->post)){
            foreach($req->post as $key =>$val){
                $_POST[$key]=$val;
            }
        }

        //打开输出缓冲
        ob_start();
        try{
            // 2. 执行应用
            think\App::run()->send();
        }catch (\Exception $e){
            echo "message:".$e->getMessage().PHP_EOL;
            echo $e->getTraceAsString().PHP_EOL;

        }
        $data=ob_get_contents();
        ob_end_clean();

        $res->end($data);
        //$http->close();

    }

    /*
    监听websocket打开事件
    */
    public function onOpen($svr,$req){
        Syn_redis::getInstance()->SADD(\think\Config::get("syn_redis.user"),$req->fd);

    }

    /*
       监听websocket消息事件
       */
    public function onMessage($svr,$frame){
       /*swoole_timer_tick(1000,function($timer_id) use($svr,$frame){
            $time=date('Y-m-d H-i-s');
            $svr->push($frame->fd,$time);
        });*/
       $port=$svr->ports[0];
       foreach($port->connections as $_fd){
           if($svr->exist($_fd)){
               $svr->push($_fd,$frame->data);
           }
       }
    }

    /*
    监听websocket关闭事件
    */
    public function onClose($svr,$fd){
        echo "$fd close...\n";
        \app\common\Syn_redis::getInstance()->SREM(\think\Config::get("syn_redis.user"),$fd);
    }

    public function onWorkerStop($svr,$worker_id){

    }

    /*
    监听task任务事件
    */
    public function onTask($srv,$task_id,$worker_id,$data){
        $task=new \app\common\Task();
        $method=$data['method'];
        return $task->$method($data['data']);
    }
    /*
       监听task任务完成事件
       */
    public function onFinish($srv,$task_id,$data){
    }

}

$ws=new WebSocket([
    'document_root' => __DIR__.'/../public/static',
    'enable_static_handler' => true,
    'worker_num'   =>8
]);
